package com.nefu.softlab.xjwc.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.nefu.softlab.xjwc.mapper.ActivityMapper;
import com.nefu.softlab.xjwc.mapper.ProjectMapper;
import com.nefu.softlab.xjwc.mapper.RedisMapper;
import com.nefu.softlab.xjwc.mapper.ScoreMapper;
import com.nefu.softlab.xjwc.model.Activity;
import com.nefu.softlab.xjwc.model.Project;
import com.nefu.softlab.xjwc.model.Score;
import com.nefu.softlab.xjwc.model.vo.ScoreVo;
import com.nefu.softlab.xjwc.service.ScoreService;
import com.nefu.softlab.xjwc.utils.JsonUtil;
import com.nefu.softlab.xjwc.utils.LoggerUtil;
import com.nefu.softlab.xjwc.utils.XJWCException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author : Ar1es
 * @date : 2020/2/8
 * @since : Java 8
 */
@Service
public class ScoreServiceImpl implements ScoreService {

    private final ScoreMapper scoreMapper;
    private final LoggerUtil loggerUtil;
    private final ActivityMapper activityMapper;
    private final RedisMapper redisMapper;
    private final ProjectMapper projectMapper;

    @Autowired
    public ScoreServiceImpl(ScoreMapper scoreMapper, LoggerUtil loggerUtil, ActivityMapper activityMapper, RedisMapper redisMapper, ProjectMapper projectMapper) {
        this.scoreMapper = scoreMapper;
        this.loggerUtil = loggerUtil;
        this.activityMapper = activityMapper;
        this.redisMapper = redisMapper;
        this.projectMapper = projectMapper;
    }


    @Override
    public double selectScoreIsExist(Score score) throws XJWCException {

        int flag = scoreMapper.selectScoreIsExist(score);
        if (0 < flag) {
            return scoreMapper.selectScore(score);
        } else {
            throw new XJWCException("查询评分失败，请重试");
        }
    }

    @Override
    public double selectOverScoreTag(Score score) throws XJWCException {
        return 0;
    }

    @Override
    public List<Map<String, Object>> selectScoreByProject(Score score) throws XJWCException {

        List<ScoreVo> list = scoreMapper.selectScoreByProject(score);

        if (list == null) {
            throw new XJWCException("查询评分失败，请重试");
        }

        List<Map<String, Object>> al = new ArrayList<>();
        list.parallelStream().forEach(ScoreVo -> {
            Map<String, Object> map = new HashMap<>();
            map.put("scoreId", ScoreVo.getScoreId());
            map.put("userId", ScoreVo.getUserId());
            map.put("projectId", ScoreVo.getProjectId());
            /**
             * "利用JSONArray中的parse方法来解析json数组字符串"
             */
            String mark = ScoreVo.getScore();
            map.put("score", JSONArray.parse(mark));
            map.put("phone", ScoreVo.getPhone());
            map.put("userName", ScoreVo.getUserName());
            map.put("message", ScoreVo.getMessage());
            map.put("type", ScoreVo.getType());
            al.add(map);
        });

        return al;


    }

    @Override
    public int selectScoreNumberByProject(Score score) throws XJWCException {

        int flag = scoreMapper.selectScoreNumberByProject(score);
        if (0 < flag) {
            return flag;
        } else {
            throw new XJWCException("查询评分失败，请重试");
        }
    }

    @Override
    public boolean selectScoreIsOver(Score score) throws XJWCException {
        List<Activity> list0 = activityMapper.selectActivityByProjectId(score.getProjectId());

        if (list0.size() != 1) {
            throw new XJWCException("查询失败，请检查活动是否存在");
        }
        Activity act = list0.get(0);

        if (redisMapper.hasKey(act.getActivityId().toString())) {
            List<Map<String, Object>> exist = (List<Map<String, Object>>) redisMapper.get(act.getActivityId().toString());
            if(exist.size() == scoreMapper.selectScoreNumberByProject(score)) {
                return true;
            }
        } else {
            throw new XJWCException("查询失败，请检查活动是否存在");
        }

        return false;
    }

    @Override
    public int insertScore(ScoreVo scoreVo) throws XJWCException {

        Score score = new Score();
        score.setProjectId(scoreVo.getProjectId());
        score.setUserId(scoreVo.getUserId());

        int ex = scoreMapper.selectScoreIsExist(score);
        if (ex == 1) {
            throw new XJWCException("已经评分完成");
        }

        List<Activity> list0 = activityMapper.selectActivityByProjectId(scoreVo.getProjectId());

        if (null == list0 || list0.size() != 1) {
            throw new XJWCException("查询失败，请检查活动是否存在");
        }
        Activity act = list0.get(0);

        int flag = 0;
        if (redisMapper.hasKey(act.getActivityId().toString())) {
            List<Map<String, Object>> list = (List<Map<String, Object>>) redisMapper.get(act.getActivityId().toString());
            for (Map<String, Object> m : list) {
                if (scoreVo.getUserId().equals(m.get("userId"))) {
                    String scoreJson = JsonUtil.getJsonString(scoreVo.getTag());

                    score.setScore(scoreJson);
                    score.setMessage(scoreVo.getMessage());

                    flag = scoreMapper.insertScore(score);
                    if (0 >= flag) {
                        throw new XJWCException("添加评分失败，请重试");
                    }
                    break;
                }
            }
        } else {
            throw new XJWCException("添加评分失败，请重试");
        }

        return flag;
    }

    @Override
    public int updateScore(ScoreVo scoreVo) throws XJWCException {
        String scoreJson = JsonUtil.getJsonString(scoreVo.getTag());

        Score score = new Score();
        score.setScore(scoreJson);
        score.setMessage(scoreVo.getMessage());
        score.setScoreId(scoreVo.getScoreId());

        int flag = scoreMapper.updateScore(score);
        if (0 < flag) {
            return flag;
        } else {
            throw new XJWCException("修改评分失败或未评分，请重试");
        }
    }

    @Override
    public int deleteScore(Score score) throws XJWCException {
        int flag = scoreMapper.deleteScore(score);
        if (0 < flag) {
            return flag;
        } else {
            throw new XJWCException("删除评分失败，请重试");
        }
    }

    @Override
    public String calculateScore(Score score) throws XJWCException {
        List<ScoreVo> list = scoreMapper.selectScoreByProject(score);
        int size = list.size();
        if (null == list) {
            throw new XJWCException("查询失败，请检查项目是否存在");
        }

        // 获取有几项评分标准
        List<Map<String, Object>> getNum = (List<Map<String, Object>>) JSONArray.parse(list.get(0).getScore());
        int num = getNum.size();

        // 最大值列表
        int[] max = new int[num];
        Arrays.fill(max, -1);

        // 最小值列表
        int[] min = new int[num];
        Arrays.fill(min, 101);

        //每一项总分，一会减最小值最大值
        int[] sum = new int[num];

        //权重列表
        double[] parts = new double[num];

        list.parallelStream().forEach(ScoreVo -> {
            String mark = ScoreVo.getScore();
            List<Map<String, Object>> scoreList = (List<Map<String, Object>>) JSONArray.parse(mark);
            scoreList.parallelStream().forEach(map0 -> {

                Integer index = Integer.valueOf(map0.get("index").toString());
                Integer value = Integer.valueOf(map0.get("value").toString());
                max[index] = Math.max(max[index], value);
                min[index] = Math.min(min[index], value);
                sum[index] += value;
                parts[index] = Double.valueOf(map0.get("part").toString());
            });
        });

        double result = 0;
        for (int i = 0; i < num; i++) {
            double res = sum[i] - max[i] - min[i];
            result += res;
        }
        double ans = result / (size - 2);

        //转化为String，四舍五入更精确
        String l = String.format("%.2f", ans);
        score.setScore(l);
        int flag = projectMapper.updateProjectScore(score);
        if (0 >= flag) {
            throw new XJWCException("分数计算失败，请重试！");
        }
        loggerUtil.info("模式3计算分数： " + l);

        return l;
    }

    @Override
    @Transactional
    public int deleteScoreByActivityId(Integer activityId) throws XJWCException {
        List<Project> projectIds = projectMapper.selectAllProjectByActivityId(activityId);
        for (Project p : projectIds) {
            if (scoreMapper.selectScoreIsExistByProId(p.getProjectId()) > 0) {
                int flag = scoreMapper.deleteScore(new Score(p.getProjectId()));
                if (0 > flag) {
                    throw new XJWCException("删除分数表失败，请重试！");
                }
            }
        }
        return 1;
    }
}
